#pragma once

#include "../../Log/TraceLog.h"
#include "json_reflection_utility.h"
//#include "WebLogger.h"

//#define WEB_MODULE   MAKE_LOG_MODULE("Web API")

template<typename T>
struct GenaralOutput : JsonReflectionBase
{
    int code;
    std::string description;
    T data;

    GenaralOutput() : code(-1) { description = "--"; }

    GenaralOutput(int errCode, const std::string &errDescription = "unknow error") : code(errCode), description(errDescription)
    {
    }

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_3(code, description, data)
    REFLECT_WEBJSON_INPUT_ARGS_NUM_3(code, description, data)
};

//固定的TcpJson头
struct DevTcpJsonHeader : JsonReflectionBase
{
    std::string target;
    int request_type;//1.代表请求  2代表响应

    REFLECT_WEBJSON_INPUT_ARGS_NUM_2(target, request_type)
    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_2(target, request_type)
};

template<typename T>
struct GenaralDevTcpJsonOutputContent : JsonReflectionBase
{
    int code;
    std::string description;
    T data;

    GenaralDevTcpJsonOutputContent() : code(-1) { description = "--"; }

    GenaralDevTcpJsonOutputContent(int errCode, const std::string &errDescription = "unknow error") : code(errCode), description(errDescription)
    {
    }

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_3(code, description, data)
    REFLECT_WEBJSON_INPUT_ARGS_NUM_3(code, description, data)
};

template<>
struct GenaralDevTcpJsonOutputContent<void> : JsonReflectionBase
{
    int code;
    std::string description;

    GenaralDevTcpJsonOutputContent() : code(-1) { description = "--"; }

    GenaralDevTcpJsonOutputContent(int errCode, const std::string &errDescription = "unknow error") : code(errCode), description(errDescription)
    {
    }

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_2(code, description)
    REFLECT_WEBJSON_INPUT_ARGS_NUM_2(code, description)
};

template<typename T>
struct GenaralDevTcpJsonOutput : JsonReflectionBase
{
    DevTcpJsonHeader head;
    GenaralDevTcpJsonOutputContent<T> request_content;

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_2(head, request_content)
    REFLECT_WEBJSON_INPUT_ARGS_NUM_2(head, request_content)
};

template<typename T>
struct GenaralDevTcpJsonOutputIns : JsonReflectionBase
{
    DevTcpJsonHeader head;
    T request_content;

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_2(head, request_content)
    REFLECT_WEBJSON_INPUT_ARGS_NUM_2(head, request_content)
};

template<>
struct GenaralOutput<void> : JsonReflectionBase
{
    int code;
    std::string description;

    GenaralOutput(int errCode, const std::string &errDescription = "unknow error") : code(errCode), description(errDescription)
    {
    }

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM_2(code, description)
    REFLECT_WEBJSON_INPUT_ARGS_NUM_2(code, description)
};

struct CommonOutput : JsonReflectionBase//共用输出
{
};


template<typename T>
struct GeneralPageInfo
{
    typedef T filter_type;

    int num;  // 个数
    int page; // 页数
    int total;// 总数
    //std::optional<T> filter;

    GeneralPageInfo()
    {
        num = 0;
        page = 0;
        total = 0;
    }
};

template<>
struct GeneralPageInfo<void>
{
    int num;  // 个数
    int page; // 页数
    int total;// 总数

    GeneralPageInfo()
    {
        num = 0;
        page = 0;
        total = 0;
    }
};


//根据total, num 调整page
template<typename T>
void correctPageInfo(GeneralPageInfo<T> &pageInfo)
{
    if (pageInfo.page < 1)
    {
        pageInfo.page = 1;
    }

    if (pageInfo.page == 1)
    {
        return;
    }

    int need_total = (pageInfo.page - 1) * pageInfo.num + 1;
    if (pageInfo.total >= need_total)
    {
        return;
    }

    pageInfo.page = pageInfo.total / pageInfo.num;
    if (pageInfo.total % pageInfo.num != 0)
    {
        ++pageInfo.page;
    }

    if (pageInfo.page < 1)
    {
        pageInfo.page = 1;
    }
}

//处理请求
template<typename _In, typename _Out>
static int GenaralOperator(cJSON *pJson, std::string &strJsonBuffer, _In &input, _Out &output, std::function<int(_In &, _Out &, std::string &)> func)
{

    std::string strDesc;

    //将最终调用结果的描述写入日志对象
    /*
	std::shared_ptr<void> raii_call_desc((void*)(1), [&strDesc](void*) {
		WebLoggerThreadObject::Get().setDescribe(strDesc);
	});*/

    std::shared_ptr<cJSON *> raii_output_str(new cJSON *, [&strJsonBuffer](cJSON **ppOutPutJson) {
        if (ppOutPutJson == nullptr)
        {
            return;
        }

        if (*ppOutPutJson != nullptr)
        {
            strJsonBuffer = JsonHandler::JsonToString(*ppOutPutJson);
            cJSON_Delete(*ppOutPutJson);
        }

        delete ppOutPutJson;
    });

    //输入
    if (!input.parseWebJsonInput(pJson))
    {
        strDesc = "param error";
        GenaralOutput<void> output(1, strDesc);
        *raii_output_str = output.genarateWebJsonOutput();
        TRACE_LOG_A(nullptr, TRACE_LOG_LEVEL_ERROR, "Json obj parse failed");

        return -1;
    }

    int nReturnCode = 0;

    try
    {
        nReturnCode = func(input, output, strDesc);
        if (nReturnCode == 0 && strDesc.empty())
        {
            strDesc = "成功";
        }
    }
    catch (const std::exception &e)
    {
        TRACE_LOG_A(nullptr, TRACE_LOG_LEVEL_ERROR, "unprocess  exception: %s, ", e.what());
        assert(1 != 1);
        strDesc = std::string("catch execption:") + e.what();
        GenaralOutput<void> output(-111110000, strDesc);
        *raii_output_str = output.genarateWebJsonOutput();
        return -1;
    }

    //输出
    if (nReturnCode == 0)
    {
        GenaralOutput<_Out> genaral_output(nReturnCode, strDesc);
        genaral_output.data = std::move(output);
        *raii_output_str = genaral_output.genarateWebJsonOutput();
    }
    else
    {
        GenaralOutput<void> genaral_output(nReturnCode, strDesc);
        *raii_output_str = genaral_output.genarateWebJsonOutput();
    }

    return 0;
}
